package inutan.common.context;

import inutan.common.constant.DataConstant;
import inutan.common.kit.InnerKit;
import inutan.common.kit.PackIdKit;
import inutan.common.inner.protocol.InnerMessage;
import org.ricks.common.lang.Logger;
import org.ricks.net.AioSession;
import org.ricks.net.DefaultContext;
import org.ricks.net.DefaultPacket;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author chenwei
 * @Description:这种结构体，cmd & byte[] 太过简单
 * IO-Game 返回客户端会带上状态码，错误信息（简化网络消息传输，不用带上错误信息，知道错误码就可以定位错误原因）。心跳包 业务包 区分，pb 直接解析所有信息。
 * 还有一种方式，自定义协议头。包体
 * @date 2021/5/2720:23
 */
public class FlowContext<T> extends DefaultContext<T> {

    private List<InnerMessage> toClients = new ArrayList<>(Byte.MAX_VALUE);
    private AioSession session;

    /** 业务方法的返回值 */
    private Object methodResult;
    /** userId */
    private long userSessionId;
    private long userId;
    private short responseStatus;
    /** true 业务方法有异常 */
    private boolean error;
    private int packageId;
    private Set<Long> toUserIds = new HashSet<>();
    public FlowContext(AioSession session, T t) {
        super(session, t);
        this.session = session;
    }

    public void sendResponse (InnerMessage message) {
        if(session != null && !session.isInvalid()){
            session.send(message);
        } else {
            Logger.info("session null");
        }
    }

    public void sendResponse (byte state,short cmd, Object data) {
        InnerMessage innerMessage = InnerKit.createInnerMessage(cmd,data);
        innerMessage.userId = userId;
        innerMessage.toUserIds = toUserIds;
        innerMessage.state = state;
        innerMessage.userSessionId = userSessionId;
//        session.sendResponse(innerMessage);
        if(state == DataConstant.RUTE_MESSAGE) session.send(innerMessage); else toClients.add(innerMessage);
    }

    public void sendResponse (byte state,short cmd) {
        InnerMessage innerMessage = InnerKit.createInnerMessage(cmd,null);
        innerMessage.userId = userId;
        innerMessage.toUserIds = toUserIds;
        innerMessage.state = state;
        innerMessage.data = new byte[0];
        innerMessage.userSessionId = userSessionId;
        if(state == DataConstant.RUTE_MESSAGE) session.send(innerMessage); else toClients.add(innerMessage);
    }

    @Override
    public void send (Object message) {
        session.send(message);
    }

    public AioSession getSession() {
        return session;
    }

    public Object getMethodResult() {
        return methodResult;
    }

    public void setMethodResult(Object methodResult) {
        this.methodResult = methodResult;
    }

    public long getUserSessionId() {
        return userSessionId;
    }

    public void setUserSessionId(long userSessionId) {
        this.userSessionId = userSessionId;
    }

    public long getUserId() {
        return userId;
    }

    public void setUserId(long userId) {
        this.userId = userId;
    }

    public short getResponseStatus() {
        return responseStatus;
    }

    public void setResponseStatus(short responseStatus) {
        this.responseStatus = responseStatus;
    }

    public Set<Long> getToUserIds() {
        return toUserIds;
    }

    public void setToUserIds(Set<Long> toUserIds) {
        this.toUserIds = toUserIds;
    }

    public boolean isError() {
        return error;
    }

    public void setError(boolean error) {
        this.error = error;
    }

    public int getPackageId() {
        return packageId;
    }

    /**
     * 异常
     * @param packageId
     */
    public void setPackageId(int packageId) {
        this.packageId = packageId;
    }

    public void writeAndFlush() {
        int packageId = PackIdKit.merge(getPackageId(),(byte) toClients.size());
        toClients.forEach(msg -> {
            msg.setPackageId(packageId);
            session.send(msg);
        });
    }
}
